package com.yx.cloud.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.yx.cloud.R;
import com.yx.cloud.utils.DisplayUtil;
import com.yx.cloud.utils.StringUtils;

import androidx.annotation.Nullable;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

public class LockView extends View {
    private Paint mPaintOuterFill;//外圆填充画笔
    private Paint mPaintOuterStroke;//外圆描边画笔
    private Paint mPaintInner;//内圆画笔
    private Paint mPaintLine;//连线的画笔
    private float mOuterStrokeWidth = DisplayUtil.dp2px(getContext(),1);//外圆描边宽度
    private int mRowCount = 3;//行数
    private int mColumnCount = 3;//列数
    private ArrayList<LockItem> mLockItems;//锁圆圈集合
    private int mColorSuccess = getContext().getColor(R.color.select_inner_fill_blue);//解锁成功的颜色
    private int mColorFailure = getContext().getColor(R.color.error_inner_fill_red);//解锁失败的颜色
    private int mColorUnSelect = getContext().getColor(R.color.unselect_outer_stroke_gary);//未选中的颜色
    private int mColorSuccessOuterFill = getContext().getColor(R.color.select_outer_fill_blue);//选中时外圆的填充颜色
    private int mColorFailureOuterFill = getContext().getColor(R.color.error_outer_fill_red);//密码错误选中时外圆的填充颜色
    private int mColorSelect =getContext().getColor(R.color.select_inner_fill_blue);//选中的颜色
    private int mColorShow = mColorSelect;//这个颜色是解锁时、验证密码成功或失败的颜色、默认是选中时的颜色（这个颜色会根据不同状态来回切换）
    private int mColorOuterFill = mColorSuccessOuterFill;
    private float mOuterRadius,mInnerRadius;
    private Path mLinePathSelect;//连线的路径
    private PointF mPrePoint;//手指连接的上一个点
    private PointF mPointTouch;//手指触摸的点
    private ArrayList<Integer> mLockSelectPassRecord;//按顺序记录选中的连接点
    private String mPass = "1235789";//正确的密码
    private CheckPasswordCallBack checkPasswordCallBack;

    public void setPass(String mPass) {
        this.mPass = mPass;
    }

    public String getPass() {
        return mPass;
    }

    public void addCheckPasswordCallBack(CheckPasswordCallBack checkPasswordCallBack) {
        this.checkPasswordCallBack = checkPasswordCallBack;
    }

    public LockView(Context context) {
        this(context,null);
    }

    public LockView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaintOuterFill = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintOuterFill.setStyle(Paint.Style.FILL);
        mPaintOuterFill.setColor(mColorOuterFill);

        mPaintOuterStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintOuterStroke.setStyle(Paint.Style.STROKE);
        mPaintOuterStroke.setStrokeWidth(mOuterStrokeWidth);

        mPaintInner = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintInner.setStyle(Paint.Style.FILL);

        mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintLine.setStyle(Paint.Style.STROKE);
        mPaintLine.setStrokeJoin(Paint.Join.ROUND);
        mPaintLine.setStrokeCap(Paint.Cap.ROUND);

        mLockItems = new ArrayList<>();
        mLockSelectPassRecord = new ArrayList<>();

        mLinePathSelect = new Path();
        mPrePoint = new PointF(0,0);
        mPointTouch = new PointF(0,0);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mOuterRadius = DisplayUtil.dp2px(getContext(),24);//外圆的半径
        mInnerRadius = DisplayUtil.dp2px(getContext(),10);//内圆半径
        mPaintLine.setStrokeWidth(DisplayUtil.dp2px(getContext(),1));//连线的宽度设为1dp
        initLockItems();
    }

    /**
     * 添加锁Item
     */
    private void initLockItems() {
        if(mLockItems == null){
            mLockItems = new ArrayList<>();
        }
        mLockItems.clear();
        //行
        for(int x = 0 ; x < mRowCount ; x++){
            float circleY;//Y轴坐标
            if(x == 0){
                //第一行
                circleY = mOuterRadius + DisplayUtil.dp2px(getContext(),1);
                //circleY = mOuterRadius + mOuterRadius/2;
            }else {
                circleY = mOuterRadius * (2 * x + 1) + DisplayUtil.dp2px(getContext(),50) * x ;
                //circleY = (mOuterRadius * 2 + mOuterRadius / 2) * x + mOuterRadius + mOuterRadius/2;//(mOuterRadius*2 + mOuterRadius/2)为大于第一行的圆心与上一行圆心的距离，mOuterRadius + mOuterRadius/2则为第一行圆心与控件顶部的距离
            }
            //列
            for(int y = 0 ; y < mColumnCount ; y++){
                float circleX;//X轴坐标
                if(y == 0){
                    //第一行
                    circleX = mOuterRadius + DisplayUtil.dp2px(getContext(),1);;
                    //circleX = mOuterRadius + mOuterRadius/2;
                }else{
                    circleX = mOuterRadius * (2 * y + 1)  + DisplayUtil.dp2px(getContext(),50) * y;
                    //circleX = (mOuterRadius*2 + mOuterRadius/2)*y+mOuterRadius + mOuterRadius/2;
                }
                LockItem lockItem = new LockItem();
                PointF pointF = new PointF(circleX,circleY);
                RectF rectFInner = new RectF(circleX - mInnerRadius,circleY - mInnerRadius,circleX+mInnerRadius,circleY+mInnerRadius);
                lockItem.setCircleCenter(pointF);
                lockItem.setRectFInnerCircle(rectFInner);
                mLockItems.add(lockItem);
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for(LockItem lockItem : mLockItems){
            PointF circleCenter = lockItem.getCircleCenter();
            if(lockItem.isSelect){
                //mPaintOuterStroke.setColor(mColorShow);
                mPaintInner.setColor(mColorShow);
                mPaintOuterFill.setColor(mColorOuterFill);
                canvas.drawCircle(circleCenter.x,circleCenter.y,mOuterRadius, mPaintOuterFill);//画外圆填充
                //canvas.drawCircle(circleCenter.x,circleCenter.y,mOuterRadius, mPaintOuterStroke);//画外圆
                canvas.drawCircle(circleCenter.x,circleCenter.y,mInnerRadius, mPaintInner);//画内圆
            }else {
                mPaintOuterStroke.setColor(mColorUnSelect);
                mPaintInner.setColor(mColorUnSelect);
                canvas.drawCircle(circleCenter.x,circleCenter.y,mOuterRadius, mPaintOuterStroke);//画外圆
            }

        }

        mPaintLine.setColor(mColorShow);
        if(mPrePoint.x != 0&&mPointTouch.x != 0){
            canvas.drawLine(mPrePoint.x,mPrePoint.y,mPointTouch.x,mPointTouch.y,mPaintLine);//画点与手指间的连线
        }

        if(!mLinePathSelect.isEmpty()){
            canvas.drawPath(mLinePathSelect,mPaintLine);//画点与点间的连线
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                clearData();
                mPointTouch.x = event.getX();
                mPointTouch.y = event.getY();
                isPointOnInnerCircle(event);
                if(checkPasswordCallBack != null){
                    checkPasswordCallBack.onReset();
                }
                return true;
            case MotionEvent.ACTION_MOVE:
                mPointTouch.x = event.getX();
                mPointTouch.y = event.getY();
                isPointOnInnerCircle(event);
                break;
            case MotionEvent.ACTION_UP:
                mPointTouch.x = 0;//清除手指的连线，只剩下点之间的连线
                mPrePoint.x =0;
                //验证密码
                boolean checkResult = checkPass();
                if(checkResult){
                    //密码校验成功
                    mColorShow = mColorSuccess;//将选中的颜色设置为成功色
                    mColorOuterFill = mColorSuccessOuterFill;
                    if(checkPasswordCallBack != null){
                        checkPasswordCallBack.onSuccess();
                    }
                }else {
                    //密码校验失败
                    mColorShow = mColorFailure;//将选中的颜色设置为失败色
                    mColorOuterFill = mColorFailureOuterFill;
                    if(checkPasswordCallBack != null){
                        checkPasswordCallBack.onFailure();
                    }
                }
                invalidate();
                break;
        }
        return super.onTouchEvent(event);
    }

    /**
     * 验证密码的正确与否
     */
    private boolean checkPass(){
        if(mPass == null){
            return false;
        }
        if(mLockSelectPassRecord == null|| mLockSelectPassRecord.size() <= 0){
            return false;
        }

        boolean checkResult = true;//验证结果
        String numberStr = "";
        for (int i = 0;i< mLockSelectPassRecord.size();i++){
            numberStr = numberStr + (mLockSelectPassRecord.get(i) + 1);
        }
        String md5Str = null;
        try {
            md5Str = StringUtils.toMD5(numberStr);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        if(mPass.equals("")){
            if(mLockSelectPassRecord.size() >= 4){
                mPass = md5Str;
                return true;
            }else {
                return false;
            }
        }

        if(!mPass.equals(md5Str)){
           checkResult = false;
        }
        Log.d("LockView","password is" + mPass + "====" +"md5 is " + md5Str);
        return checkResult;
    }

    /**
     * 再次进行连接的时候对数据进行重置
     */
    private void clearData() {
        if(mPointTouch.x == 0){
            mLinePathSelect.reset();//再次点击的时候清除点连接路径
            mLockSelectPassRecord.clear();//再次点击的时候清除连接位置（即连接密码）
            mColorShow = mColorSelect;//将展示的颜色恢复默认
            mColorOuterFill = mColorSuccessOuterFill;//将选中的填充颜色恢复默认
            lockItemReset();
        }
    }

    public void resetData(){
        mLinePathSelect.reset();//再次点击的时候清除点连接路径
        mLockSelectPassRecord.clear();//再次点击的时候清除连接位置（即连接密码）
        mColorShow = mColorSelect;//将展示的颜色恢复默认
        mColorOuterFill = mColorSuccessOuterFill;//将选中的填充颜色恢复默认
        lockItemReset();
    }

    /**
     * 恢复锁Item的未选中状态
     */
    private void lockItemReset() {
        for(LockItem lockItem:mLockItems){
            lockItem.isSelect = false;
        }
    }

    public void isPointOnInnerCircle(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        boolean isContains = false;
        PointF pointFCircleCenter = null;//如果在内圆中心范围的话将线连接到内圆中心
        for(int i = 0;i<mLockItems.size();i++){
            LockItem lockItem = mLockItems.get(i);
            RectF rectFInnerCircle = lockItem.getRectFInnerCircle();
            if(!lockItem.isSelect){//只对未连接的点处理
                if(rectFInnerCircle.contains(x,y)){
                    isContains = true;
                    pointFCircleCenter = lockItem.getCircleCenter();
                    lockItem.isSelect = true;
                    mLockSelectPassRecord.add(i);//添加选中的位置
                    break;
                }
            }
        }
        if(isContains){
            if(mLinePathSelect.isEmpty()){
                mLinePathSelect.moveTo(pointFCircleCenter.x,pointFCircleCenter.y);
            }else {
                mLinePathSelect.lineTo(pointFCircleCenter.x,pointFCircleCenter.y);
            }
            mPrePoint.x = pointFCircleCenter.x;
            mPrePoint.y = pointFCircleCenter.y;
        }
        invalidate();
    }

    /**
     * 锁Item
     */
    class LockItem{
        private RectF rectFInnerCircle;//内部圆的矩形（用于判断手指是否连接）
        private PointF circleCenter;//圆的中心点
        private boolean isSelect = false;//是否选中

        public RectF getRectFInnerCircle() {
            return rectFInnerCircle;
        }

        public void setRectFInnerCircle(RectF rectFInnerCircle) {
            this.rectFInnerCircle = rectFInnerCircle;
        }

        public PointF getCircleCenter() {
            return circleCenter;
        }

        public void setCircleCenter(PointF circleCenter) {
            this.circleCenter = circleCenter;
        }

        public boolean isSelect() {
            return isSelect;
        }

        public void setSelect(boolean select) {
            isSelect = select;
        }
    }

    /**
     * 验证密码的回调
     */
    public interface CheckPasswordCallBack{
        void onFailure();//成功
        void onSuccess();//失败
        void onReset();//重新绘制
    }
}

